﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using ECSBase.Component;
using ECSBase.Component.MaskRelated;

namespace ECSBase
{
    public class EntityAdmin
    {
        internal Dictionary<int, Entity> Entities = new Dictionary<int, Entity>();
        private List<SystemBase> Systems = new List<SystemBase>();
        private List<ComponentBase> SingletenComponents = new List<ComponentBase>();

        #region Update related

        public delegate void OnWorldUpdateOnce();
        public OnWorldUpdateOnce OnWorldUpdateOnceEvent;//World update事件，在EntityAdmin.UpdateOnce()开始触发

        public delegate void OnSystemTick(SystemBase toTick);
        public OnSystemTick OnSystemTickEvent;//System tick事件，在tick函数之前触发

        public void UpdateOnce()
        {
            OnWorldUpdateOnceEvent?.Invoke();

            //DO Something
            int _systemCount = Systems.Count;
            for (int i = 0; i < _systemCount; i++)
            {
                OnSystemTickEvent?.Invoke(Systems[i]);
                if (Systems[i].WillTick())
                {
                    //Systems[i].Tick();
                    Thread newThread = new Thread(Systems[i].Tick);
                    newThread.IsBackground = false;
                    newThread.Start();
                    //newThread.Join();//违背了多线程的初衷的说
                }
            }
        }

        #endregion

        #region System related

        /// <summary>
        /// 添加一个类型是T的系统
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public T AddSystem<T>() where T : SystemBase
        {
            if (this.GetSystem<T>() != null)
            {
                throw new Exception("出现了复例系统！请检查代码！");
            }

            Type type = typeof(T);
            T newComponent = type.Assembly.CreateInstance(type.FullName) as T;
            this.Systems.Add(newComponent);

            return this.GetSystem<T>();
        }

        /// <summary>
        /// 获取第一个类型是T的系统
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T GetSystem<T>() where T : SystemBase
        {
            int _count = this.Systems.Count;
            for (int i = 0; i < _count; i++)
            {
                if (this.Systems[i].GetType() == typeof(T))
                {
                    return Systems[i] as T;
                }
            }

            return null;
        }

        /// <summary>
        /// 获取所有的T类型的系统（返回一个T类型的数组）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        [Obsolete("正常情况下System应该是单例的！", true)]
        public T[] GetSystems<T>() where T : SystemBase
        {
            List<T> _resList = new List<T>();

            int _count = this.Systems.Count;
            for (int i = 0; i < _count; i++)
            {
                if (this.Systems[i].GetType() == typeof(T))
                {
                    _resList.Add(Systems[i] as T);
                }
            }

            return _resList.ToArray();
        }

        /// <summary>
        /// 删除所有的T类系统
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public void RemoveSystem<T>() where T : SystemBase
        {
            int _count = this.Systems.Count;
            for (int i = 0; i < _count; i++)
            {
                if (this.Systems[i].GetType() == typeof(T))
                {
                    Systems.RemoveAt(i);
                }
            }
        }

        /// <summary>
        /// 清空所有的系统
        /// </summary>
        public void ClearSystem()
        {
            Systems.Clear();
        }

        #endregion

        #region SingletenComponets

        /// <summary>
        /// 添加一个类型是T的组件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public void AddSingletenComponent<T>() where T : ComponentBase
        {
            if (this.GetSingletenComponent<T>() != null)
            {
                throw new Exception("出现了复例的单例组件！");
            }

            Type type = typeof(T);
            T newComponent = type.Assembly.CreateInstance(type.FullName) as T;
            this.SingletenComponents.Add(newComponent);
        }

        /// <summary>
        /// 获取第一个类型是T的组件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T GetSingletenComponent<T>() where T : ComponentBase
        {
            int _count = this.SingletenComponents.Count;
            for (int i = 0; i < _count; i++)
            {
                if (this.SingletenComponents[i].GetType() == typeof(T))
                {
                    return SingletenComponents[i] as T;
                }
            }

            return null;
        }

        /// <summary>
        /// 删除类型为T的SingletemComponent
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public void RemoveSingletenComponent<T>() where T : ComponentBase
        {
            int _count = this.SingletenComponents.Count;
            for (int i = 0; i < _count; i++)
            {
                if (this.SingletenComponents[i].GetType() == typeof(T))
                {
                    SingletenComponents.RemoveAt(i);
                }
            }
        }

        /// <summary>
        /// 清空所有的组件
        /// </summary>
        public void ClearSingletenComponents()
        {
            SingletenComponents.Clear();
        }

        #endregion

        #region Entity related

        /// <summary>
        /// 分发ID，保证一个Admin里面的Entity都有唯一id
        /// </summary>
        private int NextId
        {
            get
            {
                int _NewId = Entities.Count;
                while (Entities.ContainsKey(_NewId) && _NewId >= 0)
                {
                    _NewId--;
                }
                while (Entities.ContainsKey(_NewId))
                {
                    _NewId++;
                }

                return _NewId;
            }
        }

        /// <summary>
        /// 将某个实体加入
        /// </summary>
        /// <param name="toAdd"></param>
        /// <returns></returns>
        public int AddEntity(Entity toAdd)
        {
            int _newId = NextId;
            toAdd.EntityID = _newId;
            Entities.Add(_newId, toAdd);

            return _newId;
        }

        /// <summary>
        /// 新建一个实体
        /// </summary>
        /// <returns></returns>
        public Entity CreateEntity()
        {
            Entity newEntity = new Entity();
            int _newId = NextId;
            newEntity.EntityID = _newId;
            Entities.Add(_newId, newEntity);

            return Entities[_newId];
        }

        /// <summary>
        /// 删除id为EntityID的实体
        /// </summary>
        /// <param name="EntityId"></param>
        public void DeleteEntity(int EntityId)
        {
            if (Entities.ContainsKey(EntityId))
            {
                Entities.Remove(EntityId);
            }
        }

        /// <summary>
        /// 获取Id为EntityID的实体
        /// </summary>
        /// <param name="EntityId"></param>
        /// <returns></returns>
        public Entity GetEntity(int EntityId)
        {
            if (Entities.ContainsKey(EntityId))
            {
                return Entities[EntityId];
            }

            return null;
        }

        /// <summary>
        /// 通过Mask获取实体集合
        /// </summary>
        /// <param name="Mask"></param>
        /// <returns></returns>
        public Entity[] GetEntities(int Mask)
        {
            List<Entity> _resList = new List<Entity>();

            foreach (var entity in Entities.Values)
            {
                if ((entity.Mask & Mask) == Mask)
                {
                    _resList.Add(entity);
                }
            }

            return _resList.ToArray();
        }

        /// <summary>
        /// 通过类型获取实体的组件切片
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T[] GetComponents<T>() where T : ComponentBase
        {
            List<T> _resList = new List<T>();
            int Mask = MaskDistributer.DefaultContainer.GetMaskOfType(typeof(T));
            foreach (var entity in Entities.Values)
            {
                if ((entity.Mask & Mask) == Mask)
                {
                    _resList.Add(entity.GetComponent<T>());
                }
            }

            return _resList.ToArray();
        }

        public void ClearEntity()
        {
            this.Entities.Clear();
        }

        #endregion


        public void Clear()
        {
            this.ClearEntity();
            this.ClearSingletenComponents();
            this.ClearSystem();
        }
    }
}
